package thread;

/**
 * @author SWJ
 * @create 2021-06-23 14:02
 * 继承下售票安全系统的安全问题
 */
public class Thread2v2 {
    public static void main(String[] args) {
        //5.创建多线程对象
        tn1 t1 = new tn1();
        tn1 t2 = new tn1();
        tn1 t3 = new tn1();
        tn1 t4 = new tn1();
        //6.以多线程的方式启动线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
//1.自定义多线程业务类
class tn1 extends Thread {
    //3.需要定义个成员变量保存票数,此种方式需要设置票数为静态
    static int tn2 = 100;
    //2.重写父类的run()
    @Override
    public void run() {
        //4.使用循环卖票
        while(true){
            /*双重校验二：使用同步代码块
             * synchronized(锁对象){容易发生数据安全问题的代码}
             * 在同步代码块中，同一时刻，同一资源只能被一个线程独享，排队
             * 注意：锁对象必须唯一，如果不唯一，还会发生安全问题
             * 如果是继承的方式的话，锁对象一般使用本类的字节码对象*/
            //synchronized (new Object()) {
            //错误，因为每个线程都会new一个object对象,锁对象不唯一
            synchronized (tn1.class) {
//                synchronized(锁对象)本类的地址值
//                {容易发生数据安全问题的代码}
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /*双重校验一：有票的时候再卖票，增加了一个判断*/
                if (tn2 > 0) {
                    //4.1 输出当前正在卖票的线程名+票数--
                    System.out.println(getName() + "=" + tn2--);
                }
                //4.2 注意设置程序的出口！没票了就停止
                if (tn2 <= 0) break;
            }
        }
    }
}
